package com.yc.cloud.admin.service.impl;

import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.admin.dto.request.HwCameraStorageStrategyCreateReqDTO;
import com.yc.cloud.admin.dto.request.HwCameraStorageStrategyUpdateReqDTO;
import com.yc.cloud.admin.dto.request.StrategyTimeslotBindReqDTO;
import com.yc.cloud.admin.dto.request.StrategyTimeslotUnbindReqDTO;
import com.yc.cloud.admin.vo.HwCameraStorageStrategyVo;
import com.yc.cloud.admin.vo.HwCameraTimeSlotVo;
import com.yc.cloud.entity.HwCameraStorageStrategy;
import com.yc.cloud.mapper.HwCameraStorageStrategyMapper;
import com.yc.cloud.admin.service.HwCameraStorageStrategyService;
import com.yc.cloud.admin.service.HwCameraTimeSlotService;
import com.yc.cloud.api.constants.SystemConfigConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.common.basic.exception.Asserts;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;
import java.util.Objects;
import java.util.List;
import java.util.stream.Collectors;
import com.yc.cloud.entity.HwCameraStorageRelation;
import com.yc.cloud.entity.HwCameraStorageStrategyTimeslotRelation;
import com.yc.cloud.mapper.HwCameraStorageRelationMapper;
import com.yc.cloud.mapper.HwCameraStorageStrategyTimeslotRelationMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 摄像头存储策略主表 服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-09-15
 */
@Service
@Slf4j
public class HwCameraStorageStrategyServiceImpl extends ServiceImpl<HwCameraStorageStrategyMapper, HwCameraStorageStrategy> implements HwCameraStorageStrategyService {

    @Resource
    private HwCameraStorageRelationMapper relationMapper;

    @Resource
    private HwCameraStorageStrategyTimeslotRelationMapper timeslotRelationMapper;
    
    @Resource
    private HwCameraTimeSlotService hwCameraTimeSlotService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HwCameraStorageStrategyVo create(HwCameraStorageStrategyCreateReqDTO createReqDTO) {
        HwCameraStorageStrategy entity = new HwCameraStorageStrategy();
        BeanUtils.copyProperties(createReqDTO, entity);
        
        // 如果设置为全局策略，需要先将其他策略设为非全局
        if (entity.getIsGlobalDefault() != null && entity.getIsGlobalDefault().equals(SystemConfigConstants.GLOBAL_STRATEGY_YES)) {
            clearOtherGlobalStrategies(null); // 创建时没有ID，传null
        }
        
        boolean success = save(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HwCameraStorageStrategyVo update(HwCameraStorageStrategyUpdateReqDTO updateReqDTO) {
        // 1. 校验待更新的记录是否存在
        if (getById(updateReqDTO.getId()) == null) {
            Asserts.fail("记录不存在，无法更新");
        }
        
        HwCameraStorageStrategy entity = new HwCameraStorageStrategy();
        BeanUtils.copyProperties(updateReqDTO, entity);
        
        // 2. 如果设置为全局策略，需要先将其他策略设为非全局
        if (entity.getIsGlobalDefault() != null && entity.getIsGlobalDefault().equals(SystemConfigConstants.GLOBAL_STRATEGY_YES)) {
            clearOtherGlobalStrategies(entity.getId());
        }
        
        boolean success = updateById(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    public CommonPage<HwCameraStorageStrategyVo> list(BasePageReqDTO pageReqDTO) {
        QueryWrapper<HwCameraStorageStrategy> queryWrapper = new QueryWrapper<>();

        // 排序
        if (StrUtil.isNotEmpty(pageReqDTO.getSortBy())) {
            // 注意：pageReqDTO.getSortBy() 需要是数据库中的列名（驼峰转下划线），请注意防护SQL注入
            if (Objects.equals(BasePageReqDTO.ORDER_DESC, pageReqDTO.getOrder())) {
                queryWrapper.orderByDesc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            } else {
                queryWrapper.orderByAsc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            }
        }

        // 关键字模糊查询
        if (StrUtil.isNotEmpty(pageReqDTO.getKeyword())) {
            // TODO: 请根据业务需求，修改需要模糊查询的字段，以下为示例
            // queryWrapper.and(wrapper -> wrapper.like("name", pageReqDTO.getKeyword())
            //                                   .or()
            //                                   .like("description", pageReqDTO.getKeyword()));
        }
        
        // 根据 page 参数决定是否分页
        if (Boolean.TRUE.equals(pageReqDTO.getPage())) {
            Page<HwCameraStorageStrategy> page = new Page<>(pageReqDTO.getPageNum(), pageReqDTO.getPageSize());
            Page<HwCameraStorageStrategy> dbPage = baseMapper.selectPage(page, queryWrapper);
            IPage<HwCameraStorageStrategyVo> voPage = dbPage.convert(this::convertToVo);
            return CommonPage.restPage(voPage);
        } else {
            List<HwCameraStorageStrategy> allRecords = baseMapper.selectList(queryWrapper);
            CommonPage<HwCameraStorageStrategyVo> result = new CommonPage<>();
            result.setList(convertToVoList(allRecords));
            result.setTotal((long) allRecords.size());
            result.setPageNum(1);
            result.setPageSize(allRecords.size());
            result.setTotalPage(1);
            return result;
        }
    }

    @Override
    public HwCameraStorageStrategyVo getVOById(Long id) {
        HwCameraStorageStrategy entity = getById(id);
        return convertToVo(entity);
    }

    @Override
    public List<HwCameraStorageStrategyVo> convertToVoList(List<HwCameraStorageStrategy> entityList) {
        if (entityList == null) {
            return null;
        }
        return entityList.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    private HwCameraStorageStrategyVo convertToVo(HwCameraStorageStrategy entity) {
        if (entity == null) {
            return null;
        }
        HwCameraStorageStrategyVo vo = new HwCameraStorageStrategyVo();
        BeanUtils.copyProperties(entity, vo);

        //获取已绑定的时间段
        List<HwCameraTimeSlotVo> timeSlots = hwCameraTimeSlotService.getTimeslotsByStorageStrategyId(entity.getId());
        vo.setTimeSlots(timeSlots);
        return vo;
    }

    @Override
    public HwCameraStorageStrategy get(Long id) {
        return getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        // 1. 校验待删除的记录是否存在
        if (getById(id) == null) {
            Asserts.fail("记录不存在，无法删除");
        }
        return removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setAsGlobalDefault(Long strategyId) {
        // 1. 校验策略是否存在
        HwCameraStorageStrategy strategy = getById(strategyId);
        if (strategy == null) {
            Asserts.fail("策略不存在");
        }

        // 2. 取消当前的全局默认策略
        baseMapper.update(null, 
            new UpdateWrapper<HwCameraStorageStrategy>()
                .eq(HwCameraStorageStrategy.IsGlobalDefault, SystemConfigConstants.GLOBAL_STRATEGY_YES)
                .set(HwCameraStorageStrategy.IsGlobalDefault, SystemConfigConstants.GLOBAL_STRATEGY_NO)
        );

        // 3. 设置新的全局默认策略
        strategy.setIsGlobalDefault(SystemConfigConstants.GLOBAL_STRATEGY_YES);
        return updateById(strategy);
    }

    @Override
    public HwCameraStorageStrategy getGlobalDefaultStrategy() {
        return baseMapper.selectOne(
            new QueryWrapper<HwCameraStorageStrategy>()
                .eq(HwCameraStorageStrategy.IsGlobalDefault, SystemConfigConstants.GLOBAL_STRATEGY_YES)
                .eq(HwCameraStorageStrategy.Status, SystemConfigConstants.STRATEGY_STATUS_ENABLED)
                .eq(HwCameraStorageStrategy.IsDeleted, SystemConfigConstants.STRATEGY_STATUS_DISABLED)
                .last("LIMIT 1")
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindCameraStrategy(Long cameraId, Long strategyId) {
        // 1. 校验策略是否存在
        HwCameraStorageStrategy strategy = getById(strategyId);
        if (strategy == null || strategy.getStatus().equals(SystemConfigConstants.STRATEGY_STATUS_DISABLED)) {
            Asserts.fail("策略不存在或已禁用");
        }

        // 2. 检查是否已经绑定策略
        HwCameraStorageRelation existingRelation = relationMapper.selectOne(
            new QueryWrapper<HwCameraStorageRelation>()
                .eq(HwCameraStorageRelation.CameraId, cameraId)
        );

        if (existingRelation != null) {
            // 更新现有绑定
            existingRelation.setStrategyId(strategyId);
            return relationMapper.updateById(existingRelation) > 0;
        } else {
            // 创建新绑定
            HwCameraStorageRelation relation = new HwCameraStorageRelation();
            relation.setCameraId(cameraId);
            relation.setStrategyId(strategyId);
            return relationMapper.insert(relation) > 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbindCameraStrategy(Long cameraId) {
        return relationMapper.update(null,
            new UpdateWrapper<HwCameraStorageRelation>()
                .eq(HwCameraStorageRelation.CameraId, cameraId)
        ) > 0;
    }

    @Override
    public HwCameraStorageStrategy getCameraBindStrategy(Long cameraId) {
        HwCameraStorageRelation relation = relationMapper.selectOne(
            new QueryWrapper<HwCameraStorageRelation>()
                .eq(HwCameraStorageRelation.CameraId, cameraId)
        );

        if (relation != null) {
            return getById(relation.getStrategyId());
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindTimeslots(StrategyTimeslotBindReqDTO bindReqDTO) {
        Long strategyId = bindReqDTO.getStrategyId();
        
        // 1. 验证策略是否存在
        if (getById(strategyId) == null) {
            Asserts.fail("策略不存在");
        }

        try {
            // 2. 先移除该策略的所有时间段绑定
            timeslotRelationMapper.delete(
                new QueryWrapper<HwCameraStorageStrategyTimeslotRelation>()
                    .eq(HwCameraStorageStrategyTimeslotRelation.StrategyId, strategyId)
            );

            // 3. 批量插入新的绑定关系
            for (StrategyTimeslotBindReqDTO.TimeSlotBindInfo timeSlotInfo : bindReqDTO.getTimeSlots()) {
                HwCameraStorageStrategyTimeslotRelation relation = new HwCameraStorageStrategyTimeslotRelation();
                relation.setStrategyId(strategyId);
                relation.setTimeSlotId(timeSlotInfo.getTimeSlotId());
                relation.setStatus(SystemConfigConstants.RELATION_STATUS_ENABLED.byteValue());
                timeslotRelationMapper.insert(relation);
            }
            return true;
        } catch (Exception e) {
            throw new RuntimeException("绑定时间段失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbindTimeslots(StrategyTimeslotUnbindReqDTO unbindReqDTO) {
        Long strategyId = unbindReqDTO.getStrategyId();
        List<Long> timeSlotIds = unbindReqDTO.getTimeSlotIds();

        // 1. 验证策略是否存在
        if (getById(strategyId) == null) {
            Asserts.fail("策略不存在");
        }

        try {
            // 2. 批量删除关联关系（逻辑删除或物理删除）
            return timeslotRelationMapper.delete(
                new QueryWrapper<HwCameraStorageStrategyTimeslotRelation>()
                    .eq(HwCameraStorageStrategyTimeslotRelation.StrategyId, strategyId)
                    .in(HwCameraStorageStrategyTimeslotRelation.TimeSlotId, timeSlotIds)
            ) > 0;
        } catch (Exception e) {
            throw new RuntimeException("解绑时间段失败: " + e.getMessage(), e);
        }
    }

    /**
     * 清除其他策略的全局默认标识
     * @param excludeId 要排除的策略ID（当前正在设置的策略）
     */
    private void clearOtherGlobalStrategies(Long excludeId) {
        UpdateWrapper<HwCameraStorageStrategy> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq(HwCameraStorageStrategy.IsGlobalDefault, SystemConfigConstants.GLOBAL_STRATEGY_YES)
                    .set(HwCameraStorageStrategy.IsGlobalDefault, SystemConfigConstants.GLOBAL_STRATEGY_NO);
        
        // 如果有要排除的ID，则不更新该记录
        if (excludeId != null) {
            updateWrapper.ne(HwCameraStorageStrategy.ID, excludeId);
        }
        
        baseMapper.update(null, updateWrapper);
        log.info("已清除其他策略的全局默认标识，排除策略ID: {}", excludeId);
    }
} 